#ifndef __SENSOR_H__
#define __SENSOR_H__

#define SENSOR_OVERTIME_LIMIT					2
#define SENSOR_MPU6050_POLL_INTERVAL			1
#define SENSOR_MPU6050_POLL_INTERVAL_OFFSET		0
#define SENSOR_HMC5883L_POLL_INTERVAL			8
#define SENSOR_HMC5883L_POLL_INTERVAL_OFFSET	0
#define SENSOR_BMP280_POLL_INTERVAL				40
#define SENSOR_BMP280_POLL_INTERVAL_OFFSET		2

#define SENSOR_STATE_NONE				0
#define SENSOR_STATE_INIT_PASS			1
#define SENSOR_STATE_INIT_FAIL			2
#define SENSOR_STATE_WORKING			3
#define SENSOR_STATE_ERROR				4

#define SENSOR_MPU6050_DYNAMIC_RANGE_ENABLE
#define SENSOR_MPU6050_DYNAMIC_RANGE_ACCEL_UPPER (32768 * 70 / 100)
#define SENSOR_MPU6050_DYNAMIC_RANGE_ACCEL_FLOOR (32768 * 30 / 100)
#define SENSOR_MPU6050_DYNAMIC_RANGE_GYRO_UPPER (32768 * 70 / 100)
#define SENSOR_MPU6050_DYNAMIC_RANGE_GYRO_FLOOR (32768 * 30 / 100)


struct mpu6050_t
{
	uint16_t state;
	uint8_t addr;
	uint8_t wait_update : 1;
	uint8_t i2c_keep : 1;
	uint8_t range_set : 1;
	uint8_t : 5;

	int32_t accel_x;		// 1 = 1/16384 g
	int32_t accel_y;
	int32_t accel_z;
	int32_t gyro_x;			// 1 = 1/131 o/s
	int32_t gyro_y;
	int32_t gyro_z;
	int32_t temperature;	// 1 = 0.01degc

	// private
	uint8_t smplrt_div;		// 0x19
	uint8_t config;
	uint8_t gyro_config;	// 0x1b
	uint8_t accel_config;

	uint8_t accel_xh;		// 0x3b
	uint8_t accel_xl;
	uint8_t accel_yh;
	uint8_t accel_yl;
	uint8_t accel_zh;
	uint8_t accel_zl;
	uint8_t temp_h;
	uint8_t temp_l;
	uint8_t gyro_xh;
	uint8_t gyro_xl;
	uint8_t gyro_yh;
	uint8_t gyro_yl;
	uint8_t gyro_zh;
	uint8_t gyro_zl;

	uint8_t pwr_mgmt_1;		// 0x6b
	uint8_t pwr_mgmt_2;

	uint8_t who_am_i;		// 0x75
};

struct hmc5883l_t
{
	uint16_t state;
	uint8_t addr;
	uint8_t wait_update : 1;
	uint8_t i2c_keep : 1;
	uint8_t : 6;

	// private
	uint8_t config_a;	// 0x00
	uint8_t config_b;
	uint8_t mode;
	uint8_t x_msb;		// 0x03 read only
	uint8_t x_lsb;
	uint8_t z_msb;
	uint8_t z_lsb;
	uint8_t y_msb;
	uint8_t y_lsb;
	uint8_t status;
	uint8_t id_a;		// 0x0a
	uint8_t id_b;
	uint8_t id_c;
};

struct bmp280_t
{
	uint16_t state;
	uint8_t addr;
	uint8_t wait_update : 1;
	uint8_t i2c_keep : 1;
	uint8_t : 6;

	int32_t temp;		// 1 = 0.01degc
	int32_t press;		// 1 = 1/10PA

	// private
	uint16_t dig_T1;	// 0x88/0x89
	int16_t dig_T2;
	int16_t dig_T3;
	uint16_t dig_P1;
	int16_t dig_P2;
	int16_t dig_P3;
	int16_t dig_P4;
	int16_t dig_P5;
	int16_t dig_P6;
	int16_t dig_P7;
	int16_t dig_P8;
	int16_t dig_P9;

	uint8_t chip_id;	// 0xd0

	uint8_t status;		// 0xf3

	uint8_t ctrl_meas;	// 0xf4
	uint8_t config;

	uint8_t press_msb;	// 0xf7
	uint8_t press_lsb;
	uint8_t press_xlsb;
	uint8_t temp_msb;
	uint8_t temp_lsb;
	uint8_t temp_xlsb;
};

struct sensor_t
{
	uint16_t rate; // kHz
	uint8_t index;
	uint8_t overtime : 4;
	uint8_t poll : 1;
	uint8_t i2c_keep : 1;
	uint8_t error : 1;
	uint8_t : 1;

	struct mpu6050_t mpu6050;
	struct hmc5883l_t hmc5883l;
	struct bmp280_t bmp280;

	// private
	struct vsfsm_t sm;
	struct vsfsm_pt_t pt;

	uint8_t buf[8];
	int16_t read_len;
	int16_t write_len;
};

void sensor_init(struct sensor_t *sensor);
void sensor_int_callback(struct sensor_t *sensor);

#endif // __SENSOR_H__

